<?php
/*
* A helper class to store data into a heirachical structure that
* can be processed into structure html.
*/
class XmlStore extends XMLWriter
{
    /**
     * $_cleanXml is flagged true once the xml has been generated however after
     * modifications this is reset to indicate that the xml needs to be re-
     * generated.
     * @var boolean
     */
    protected $_cleanXml = false;

    /**
     * $_store is locating
     * modifications this is reset to indicate that the xml needs to be re-
     * generated.
     * @var boolean
     */
    protected $_store = new stdClass();

    public __construct()
    {
       $this->create();
    }

    /**
     * __set() - method to set a variable/value in this object's private $_store
     *
     * @param string $name - programmatic name of a key, in a <key,value> pair
     * in the current store
     * @param mixed $value - value in the <key,value> pair to assign to the $name key
     * @return true
     */
    protected function __set($name, $value)
    {
        $this->_store->{$name} = $value;
        $this->_cleanXml = false;
        return true;
    }

    /**
     * __get() - method to set a variable/value in this object's private $_store
     *
     * @param string $name - programmatic name of a key for accessing
     * @return mixed -  Returns a reference to the accessed object from the store
     */
    protected function &__get($name)
    {
        return $this->_store->{$name};
    }


    /**
     * create() - Create the xml document into a stream located in the memory
     *
     * @return XmlStore -  Returns the current object
     */
    public function create()
    {
        $this->delete();
        $this->openMemory();
        return $this;
    }

    /**
     * create() - Deletes the current stream buffer from memory and toggles
     * $_cleanXml to indicate that the XML needs to be re-generated.
     *
     * @return XmlStore -  Returns the current object
     */
    public function delete() //Flush the buffer completly
    {
        $this->flush(true);
        $this->_cleanXml = false;
        return $this;
    }


    /**
     * processElement() - Iterates through all each element stored within the
     * store, then process and formats the element into the according XML
     *
     * @param string $key - programmatic name of a key for accessing
     * @param mixed $obj - the value for the key.
     * @return true
     */
    protected function processElement($key, $obj)
    {
        /*
        *  Create the starting element, and choose whether it belongs to a
        *  namespace or is a standard element and create this element.
        */
        if(isset($obj->namespace))
        {
            $this->startElementNS(null, $key, $obj->namespace)
        }
        else
        {
            $this->startElement($key);
        }

        //Iterate through the object to find juicy stuff
        foreach($obj as $key => $val)
        {
            switch($key)
            {
                case 'attributes': //Given as an Array
                    foreach($val as $attribute => $val)
                    {
                        $this->writeAttribute($attribute, $val);
                    }
                break;
                case 'cdata':
                    $this->startCData();
                    $this->writeCData($val);
                    $this->endCData();
                break;
                default:
                    switch(true)
                    {
                        case is_object($val):
                            processElement($key, $val); break;
                        case is_string($val):
                            $this->text($val); break;
                    }
            }
        }
        $this->endElement(); //Close the element after iterating through each members object
        return true;
    }

    /**
     * __toString() - Returns a useful formatted XML String.
     *
     * @return string
     */
    public function __toString()
    {
        if(!$this->_cleanXml)
        {
            foreach($this->_store as $key => $obj) //Iterate through the root elements
            {
                processElement($key, $bj);
            }
            $this->_cleanXml = true; //Set the flag
        }

        return $this->flush(false); //Simply return the xml currently stored in the buffer without deleting it
    }
}

